package model;

import java.util.ArrayList;
import java.util.Random;

import fitnessCalculationStrategy.FitnessCalculationStrategy;
import fitnessCalculationStrategy.StringParityFitnessCalculationStrategy;

public class SimpleStringOrganism implements Organism {

	private static SimpleStringOrganism idealOrganism = new SimpleStringOrganism("Hello World!"); 
	private static final int numberOfGenes = 12;	
	private static final int numberOfAlleles = 90;
	private ArrayList<Character> chromosones = new ArrayList<Character>(numberOfGenes);
	private FitnessCalculationStrategy fitnessCalculationStrategy = new StringParityFitnessCalculationStrategy();
	
	public SimpleStringOrganism()
	{
		this.chromosones = stringToCharacterArray("XXXXXXXXXXXXXXXXXXXXXXXXX");
	}
	
	public SimpleStringOrganism(String chromosones)
	{
		this.chromosones = stringToCharacterArray(chromosones);
	}
	
	public int getNumberOfGenes() {
		return numberOfGenes;
	}
	
	public ArrayList<Character> getChromosones() {
		return chromosones;
	}
	
	public String toString() {
		StringBuilder builder = new StringBuilder(chromosones.size());
		for(Character c : chromosones)
		{
			builder.append(c);
		}
		return builder.toString();
	}
	
	public void setChromosones(ArrayList<Character> chromosones) {
		this.chromosones = chromosones;
	}
	
	public void setChromosones(String chromosones) {
		this.chromosones = stringToCharacterArray(chromosones);
	}
	
	public void setChromosoneAtIndex(int index, Character chromosone)
	{
		this.chromosones.set(index, chromosone);
	}
	
	public Character getChromosoneAtIndex(int index)
	{
		return this.chromosones.get(index);
	}
	
	public boolean equals(SimpleStringOrganism simpleStringOrganism)
	{
		if(this.getChromosones().size() != simpleStringOrganism.getChromosones().size())
		{
			return false;
		}
		int i = 0;
		for(Character c: this.chromosones)
		{
			if(c != simpleStringOrganism.getChromosoneAtIndex(i++))
			{
				return false;
			}
		}
		return true;
	}
	
	private ArrayList<Character> stringToCharacterArray(String string)
	{
		ArrayList<Character> characterArray = new ArrayList<Character>(numberOfGenes);
		int i = 0;
		char[] stringChars = string.toCharArray();
		while(i < numberOfGenes)
		{
			characterArray.add((Character)stringChars[i++]);
		}
		return characterArray;
	}

	@Override
	public float calculateFitness()
	{
		try 
		{
			fitnessCalculationStrategy.setIdealOrganism(idealOrganism);
			return fitnessCalculationStrategy.calculateFitness(this);
		} 
		catch (NullPointerException e) 
		{
			e.printStackTrace();
			return 0.0f;
		}
	}
	
	public static int getNumberOfChromosones()
	{
		return numberOfGenes;
	}

	public int getNumberOfAlleles()
	{
		return numberOfAlleles;
	}
	
	public static void setIdealOrganism(SimpleStringOrganism ideal)
	{
		idealOrganism = ideal;
	}

	@Override
	public void mutate()
	{
		Random randomGenerator = new Random(System.currentTimeMillis());
		int geneToMutate = Math.abs(randomGenerator.nextInt()%numberOfGenes);
		Character newGene = new Character((char)(Math.abs(randomGenerator.nextInt())%numberOfAlleles));
		this.setChromosoneAtIndex(geneToMutate, newGene); 
	}
	
}
